package fractal;

import java.util.ArrayList;
import java.util.List;

import entity.Position;

public class GenerateurRiviere
{

	public static void generateRiver( TerrainMap pTerrain , int nbFois )
	{
		for (int i = 0; i < nbFois; i++)
			generateRiver(pTerrain);
	}

	public static void generateRiver( TerrainMap pTerrain )
	{
		Terrain[][] map = pTerrain.getMap();
		Direction[][] direction = new Direction[map.length][map.length];
		Double[][] water = new Double[map.length][map.length];
		// on set les directions(grace aux hauteurs de terrain)
		for (int i = 0; i < map[0].length; i++)
		{
			for (int j = 0; j < map.length; j++)
			{
				double hauteur = map[i][j].getHauteur();
				direction[i][j] = Direction.NO_DIRECTION;
				hauteur = manageDirection(map, direction, i, j, hauteur, Direction.NORTH);
				hauteur = manageDirection(map, direction, i, j, hauteur, Direction.NORTH_EAST);
				hauteur = manageDirection(map, direction, i, j, hauteur, Direction.NORTH_WEST);
				hauteur = manageDirection(map, direction, i, j, hauteur, Direction.SOUTH);
				hauteur = manageDirection(map, direction, i, j, hauteur, Direction.SOUTH_EAST);
				hauteur = manageDirection(map, direction, i, j, hauteur, Direction.SOUTH_WEST);
				hauteur = manageDirection(map, direction, i, j, hauteur, Direction.EAST);
				hauteur = manageDirection(map, direction, i, j, hauteur, Direction.WEST);
				// if (i > 24 && i < 26 && j > 16 && j < 18)
				// {
				// System.out.println(i + ":" + j + ":" + direction[i][j]);
				// }
				// indice eaux
				water[i][j] = map[i][j].getWater();
				map[i][j].setWater(0);
			}
		}
		// System.out.println("*************************");
		// on fait pleuvoir, on regarde ce qu'il se passe
		// System.out.println(":::::::" + water[30][22]);
		water[25][17] = water[25][17] + 40.0;
		// on fait evoluer la pluie
		for (int i = 0; i < map[0].length; i++)
		{
			for (int j = 0; j < map.length; j++)
			{
				if (water[i][j] != 0)
				{
					Direction d = direction[i][j];
					if (!d.equals(Direction.NO_DIRECTION))
					{
						int nx = d.getNewX(i);
						int ny = d.getNewY(j);
						Terrain n = map[nx][ny];
						double dif = map[i][j].getHauteur() - n.getHauteur();
						if( dif > water[i][j])
						{
							dif = water[i][j];
						}
						n.setWater(n.getWater() + dif);
						map[i][j].setWater(water[i][j] - dif);
//						System.out.println(i + ":" + j + ":" + d + ":" + map[i][j].getWater());
//						System.out.println(nx + ":" + ny + ":" + n.getWater());
//						System.out.println("----");
					}
				}
			}
		}
		// System.out.println("*************************");
	}

	protected static double manageDirection( Terrain[][] pMap , Direction[][] direction , int x , int y , double hauteur , Direction d )
	{
		int nx = d.getNewX(x);
		int ny = d.getNewY(y);
		if (nx >= 0 && nx < pMap.length && ny >= 0 && ny < pMap.length)
		{
			double nh = pMap[nx][ny].getHauteur();
			if (nh < hauteur)
			{
				direction[x][y] = d;
				hauteur = nh;
			}
		}
		return hauteur;

	}

	public static boolean[][] river( double[][] _map )
	{
		//
		boolean[][] _waterMap = new boolean[_map[0].length][_map.length];
		for (int i = 0; i < _waterMap[0].length; i++)
		{
			for (int j = 0; j < _waterMap.length; j++)
			{
				_waterMap[i][j] = false;
			}
		}
		/*
		 * List<Position> astar = AStar.getPath(new Position(_map.length / 2, _map.length / 2), new Position(0, 0), _map); if (astar != null) { for (Position p : astar) { _waterMap[p.getX()][p.getY()] = true; } }
		 */
		/*
		 * Stack<Position> river = new Stack<Position>(); List<Position> forbidden = new ArrayList<Position>(); river.push(new Position(_map.length / 2, _map.length / 2)); for (int i = 0; i < 100; i++) { Position pCurrent = river.peek(); List<Position> posiAdj = positionAdjacente(pCurrent); }
		 */
		/*
		 * int nbIteration = 100; // on part du centre; Stack<Position> pile = new Stack<Position>(); pile.push(new Position(_map.length / 2, _map.length / 2)); Position lastPosition = pile.peek(); for (int i = 0; i < nbIteration; i++) { if (!pile.isEmpty()) { Position p = pile.peek(); _waterMap[p.getX()][p.getY()] = true; double height = _map[p.getX()][p.getY()]; if (_map[p.getX() + 1][p.getY()] < height && !_waterMap[p.getX() + 1][p.getY()]) { pile.push(new Position(p.getX() + 1, p.getY())); } else if (_map[p.getX() - 1][p.getY()] < height && !_waterMap[p.getX() - 1][p.getY()]) { pile.push(new Position(p.getX() - 1, p.getY())); } else if (_map[p.getX()][p.getY() + 1] < height && !_waterMap[p.getX()][p.getY() + 1]) { pile.push(new Position(p.getX(), p.getY() + 1)); } else if (_map[p.getX()][p.getY() - 1] < height && !_waterMap[p.getX()][p.getY() - 1]) { pile.push(new Position(p.getX(), p.getY() - 1)); } else { pile.pop(); } lastPosition = p; } }
		 */
		return _waterMap;
	}

	public static List<Position> positionAdjacente( Position pDep )
	{
		List<Position> result = new ArrayList<Position>();
		/*
		 * double height = _map[pDep.getX()][pDep.getY()]; if (_map[pDep.getX() + 1][pDep.getY()] < height && !_waterMap[pDep.getX() + 1][pDep.getY()]) { result.add(new Position(pDep.getX() + 1, pDep.getY())); } if (_map[pDep.getX() - 1][pDep.getY()] < height && !_waterMap[pDep.getX() - 1][pDep.getY()]) { result.add(new Position(pDep.getX() - 1, pDep.getY())); } if (_map[pDep.getX()][pDep.getY() + 1] < height && !_waterMap[pDep.getX()][pDep.getY() + 1]) { result.add(new Position(pDep.getX(), pDep.getY() + 1)); } if (_map[pDep.getX()][pDep.getY() - 1] < height && !_waterMap[pDep.getX()][pDep.getY() - 1]) { result.add(new Position(pDep.getX(), pDep.getY() - 1)); }
		 */
		return result;
	}
}
